

#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
#include "support.h"
#include "memview.h"
#include "codeview.h"
#include "config.h"
#include "keypad.h"
#include "dialog.h"
#include "memfill.h"
#include "statusbar.h"
#include "memfill_call.h"
#include "memfill_call_table.h"

/*################## I got lazy that time (Sorry) #############*/
gint called_again;

/*################### static functions ###############*/
static gint gsim_fill_memview(gint how,gchar * data);
static gchar *get_address__(void);

/*#################### Fill the memview cell ################*/
static gint gsim_fill_memview(gint how,gchar * data)
{
	gint fill_address;
	sscanf(address,"%X",&fill_address);
	
	/*SORRY for this! - i can't change whole file(See spacial note in documentation)*/
	if(called_again==1)
	{
		fill_address++;
		snprintf(address,5,"%X",fill_address);
	}
	
	/*if data is single byte or two bytes(address)*/
	switch(how)
	{
		case 0: /*1-byte*/
			if(fill_address<gsim_values.memstart||fill_address>gsim_values.memend)
			{
				gsim_message(_("Address out of range."),GTK_MESSAGE_ERROR);
				return 1;
			}
			memview_scroll_to_address(fill_address);
			
			
			/*Set the refrence to the row for the cell in memory*/
			/*==================================================*/
			struct codeview_ref_info *new_ref=g_malloc(sizeof(*new_ref));
			new_ref->path=gtk_tree_model_get_string_from_iter(current_code_model,&current_code_iter);
			new_ref->page=current_page;
			g_object_set_data(codeview_ref,address,new_ref);
			
			gtk_list_store_set(GTK_LIST_STORE(memview_model),&memview_iter,1,data,-1);
			break;
			
		case 1:/*2-bytes*/
			if(fill_address<gsim_values.memstart||fill_address+1>gsim_values.memend)
			{
				gsim_message(_("Address out of range."),GTK_MESSAGE_ERROR);
				return 1;
			}
			
			data+=2;          /*first lower byte*/
			memview_scroll_to_address(fill_address);
			gtk_list_store_set(GTK_LIST_STORE(memview_model),&memview_iter,1,data,-1);
			
			*data='\0';
			data-=2;
			fill_address++;
			snprintf(address,5,"%X",fill_address);
			memview_scroll_to_address(fill_address);
			gtk_list_store_set(GTK_LIST_STORE(memview_model),&memview_iter,1,data,-1);
			break;
	}
	
	called_again++;
	return 0;
}

/*################## Return address from lable if any #################*/
static gchar *get_address__(void)
{
	gchar *resolved_addr;
	gchar *ans;
	
	/*check if label is there*/
	gint i,if_label=0;
	for(i=0;i<g_utf8_strlen(op1,9);i++)
	{
		if(i>3||!g_ascii_isxdigit(*(op1+i)))
		{
			if_label=1;
			break;
		}
	}
	
	if(i<3)         /*Only may be a label*/
		if_label=1;
	
	if(!if_label)
		ans=g_strndup(op1,5);
	else
	{
		/*it is label get the corrsponding address*/
		resolved_addr=g_object_get_data(gsim_label_address,op1);
		if(!resolved_addr)
		{
			gsim_message(_("No such label as specified."),GTK_MESSAGE_ERROR);
			return NULL;
		}
		ans=g_strndup(resolved_addr,5);
	}
	return ans;
}


/*######################################################################*
 *######## Routines for filling memview by various instructions ########*
 *######################################################################*/ 

gint mov(void)
{
	/* MOV M,M is not allowed*/
	if(!g_ascii_strncasecmp(op1,"M",2)&&!g_ascii_strncasecmp(op2,"M",2))
	{
		gsim_message(_("Invalid instruction MOV M,M."),GTK_MESSAGE_ERROR);
		return 1;
	}
	
	/*look for hexcode in table*/
	gint i,j;
	for(i=0;i<8;i++)
		if(!g_ascii_strncasecmp(op1,mov_lookup[i][0].op1,2))
			break;
	for(j=0;j<8;j++)
		if(!g_ascii_strncasecmp(op2,mov_lookup[i][j].op2,2))
			break;
	
	return gsim_fill_memview(0,mov_lookup[i][j].code);
}

gint aci(void)
{
	if(gsim_fill_memview(0,"CE"))
		return 1;
	return gsim_fill_memview(0,op1);
}

gint adc(void)
{
	gint i;
	for(i=0;i<8;i++)
		if(g_ascii_strncasecmp(op1,adc_lookup[i].op1,2)==0)
			break;
	return gsim_fill_memview(0,adc_lookup[i].code);
}

gint add(void)
{
	gint i;
	for(i=0;i<8;i++)
		if(g_ascii_strncasecmp(op1,add_lookup[i].op1,2)==0)
			break;
	return gsim_fill_memview(0,add_lookup[i].code);
}

gint adi(void)
{
	if(gsim_fill_memview(0,"C6"))
		return 1;
	return gsim_fill_memview(0,op1);
}

gint ana(void)
{
	gint i;
	for(i=0;i<8;i++)
		if(g_ascii_strncasecmp(op1,ana_lookup[i].op1,2)==0)
			break;
	return gsim_fill_memview(0,ana_lookup[i].code);
}
gint ani(void)
{
	if(gsim_fill_memview(0,"E6"))
		return 1;
	return gsim_fill_memview(0,op1);
}

gint cmp(void)
{
	gint i;
	for(i=0;i<8;i++)
		if(g_ascii_strncasecmp(op1,cmp_lookup[i].op1,2)==0)
			break;
	return gsim_fill_memview(0,cmp_lookup[i].code);
}

gint cpi(void)
{
	
	if(gsim_fill_memview(0,"FE"))
		return 1;
	return gsim_fill_memview(0,op1);
}

gint dcr(void)
{
	gint i;
	for(i=0;i<8;i++)
		if(g_ascii_strncasecmp(op1,dcr_lookup[i].op1,2)==0)
			break;
	return gsim_fill_memview(0,dcr_lookup[i].code);
}
gint inr(void)
{
	gint i;
	for(i=0;i<8;i++)
		if(g_ascii_strncasecmp(op1,inr_lookup[i].op1,2)==0)
			break;
	return gsim_fill_memview(0,inr_lookup[i].code);
}

gint ora(void)
{
	gint i;
	for(i=0;i<8;i++)
		if(g_ascii_strncasecmp(op1,ora_lookup[i].op1,2)==0)
			break;
	return gsim_fill_memview(0,ora_lookup[i].code);
}

gint in(void)
{
	if(gsim_fill_memview(0,"DB"))
		return 1;
	return gsim_fill_memview(0,op1);
}

gint out(void)
{
	if(gsim_fill_memview(0,"D3"))
		return 1;
	return gsim_fill_memview(0,op1);
}

gint ori(void)
{
	if(gsim_fill_memview(0,"F6"))
		return 1;
	return gsim_fill_memview(0,op1);
}

gint sbb(void)
{
	gint i;
	for(i=0;i<8;i++)
		if(g_ascii_strncasecmp(op1,sbb_lookup[i].op1,2)==0)
			break;
	return gsim_fill_memview(0,sbb_lookup[i].code);
}

gint sbi(void)
{
	if(gsim_fill_memview(0,"DE"))
		return 1;
	return gsim_fill_memview(0,op1);
}

gint sui(void)
{
	if(gsim_fill_memview(0,"D6"))
		return 1;
	return gsim_fill_memview(0,op1);
}

gint xri(void)
{
	if(gsim_fill_memview(0,"EE"))
		return 1;
	return gsim_fill_memview(0,op1);
}

gint sub(void)
{
	gint i;
	for(i=0;i<8;i++)
		if(g_ascii_strncasecmp(op1,sub_lookup[i].op1,2)==0)
			break;
	return gsim_fill_memview(0,sub_lookup[i].code);
}

gint xra(void)
{
	gint i;
	for(i=0;i<8;i++)
		if(g_ascii_strncasecmp(op1,xra_lookup[i].op1,2)==0)
			break;
	return gsim_fill_memview(0,xra_lookup[i].code);
}

gint cmc(void)
{
	return gsim_fill_memview(0,"3F");
}

gint cma(void)
{
	return gsim_fill_memview(0,"2F");
}

gint daa(void)
{
	return gsim_fill_memview(0,"27");
}
gint hlt(void)
{
	return gsim_fill_memview(0,"76");
}

gint di(void)
{
	return gsim_fill_memview(0,"F3");
}

gint ei(void)
{
	return gsim_fill_memview(0,"FB");
}

gint nop(void)
{
	return gsim_fill_memview(0,"00");
}

gint pchl(void)
{
	return gsim_fill_memview(0,"E9");
}

gint ral(void)
{
	return gsim_fill_memview(0,"17");
}

gint rar(void)
{
	return gsim_fill_memview(0,"1F");
}

gint rlc(void)
{
	return gsim_fill_memview(0,"07");
}

gint rrc(void)
{
	return gsim_fill_memview(0,"0F");
}

gint ret(void)
{
	return gsim_fill_memview(0,"C9");
}

gint rc(void)
{
	return gsim_fill_memview(0,"D8");
}

gint rnc(void)
{
	return gsim_fill_memview(0,"D0");
}

gint rp(void)
{
	return gsim_fill_memview(0,"F0");
}

gint rm(void)
{
	return gsim_fill_memview(0,"F8");
}

gint rpe(void)
{
	return gsim_fill_memview(0,"E8");
}

gint rpo(void)
{
	return gsim_fill_memview(0,"E0");
}

gint rz(void)
{
	return gsim_fill_memview(0,"C8");
}

gint rnz(void)
{
	return gsim_fill_memview(0,"C0");
}

gint rim(void)
{
	return gsim_fill_memview(0,"20");
}

gint sim(void)
{
	return gsim_fill_memview(0,"30");
}

gint sphl(void)
{
	return gsim_fill_memview(0,"F9");
}
gint stc(void)
{
	return gsim_fill_memview(0,"37");
}
gint xchg(void)
{
	return gsim_fill_memview(0,"EB");
}
gint xthl(void)
{
	return gsim_fill_memview(0,"E3");
}


gint dad(void)
{
	gint i;
	for(i=0;i<4;i++)
		if(g_ascii_strncasecmp(op1,dad_lookup[i].op1,3)==0)
			break;
	return gsim_fill_memview(0,dad_lookup[i].code);
}


gint dcx(void)
{
	gint i;
	for(i=0;i<4;i++)
		if(g_ascii_strncasecmp(op1,dcx_lookup[i].op1,3)==0)
			break;
	return gsim_fill_memview(0,dcx_lookup[i].code);
}

gint inx(void)
{
	gint i;
	for(i=0;i<4;i++)
		if(g_ascii_strncasecmp(op1,inx_lookup[i].op1,3)==0)
			break;
	return gsim_fill_memview(0,inx_lookup[i].code);
}

gint pop(void)
{
	gint i;
	for(i=0;i<4;i++)
		if(g_ascii_strncasecmp(op1,pop_lookup[i].op1,4)==0)
			break;
	return gsim_fill_memview(0,pop_lookup[i].code);
}

gint push(void)
{
	gint i;
	for(i=0;i<4;i++)
		if(g_ascii_strncasecmp(op1,push_lookup[i].op1,4)==0)
			break;
	return gsim_fill_memview(0,push_lookup[i].code);
}

gint call (void)
{
	gchar *x;
	x=get_address__();
	if(!x)
		return 1;
	if(gsim_fill_memview(0,"CD"))
	{
		g_free(x);
		return 1;
	}
	if(gsim_fill_memview(1,x))
	{
		g_free(x);
		return 1;
	}
	g_free(x);
	return 0;
}
	
gint cc (void)
{
	gchar *x;
	x=get_address__();
	if(!x)
		return 1;
	if(gsim_fill_memview(0,"DC"))
	{
		g_free(x);
		return 1;
	}
	if(gsim_fill_memview(1,x))
	{
		g_free(x);
		return 1;
	}
	g_free(x);
	return 0;
}

gint cnc (void)
{
	gchar *x;
	x=get_address__();
	if(!x)
		return 1;
	if(gsim_fill_memview(0,"D4"))
	{
		g_free(x);
		return 1;
	}
	if(gsim_fill_memview(1,x))
	{
		g_free(x);
		return 1;
	}
	g_free(x);
	return 0;
}

gint cp (void)
{
	gchar *x;
	x=get_address__();
	if(!x)
		return 1;
	if(gsim_fill_memview(0,"F4"))
	{
		g_free(x);
		return 1;
	}
	if(gsim_fill_memview(1,x))
	{
		g_free(x);
		return 1;
	}
	g_free(x);
	return 0;
}

gint cm (void)
{
	gchar *x;
	x=get_address__();
	if(!x)
		return 1;
	if(gsim_fill_memview(0,"FC"))
	{
		g_free(x);
		return 1;
	}
	if(gsim_fill_memview(1,x))
	{
		g_free(x);
		return 1;
	}
	g_free(x);
	return 0;
}

gint cpe (void)
{
	gchar *x;
	x=get_address__();
	if(!x)
		return 1;
	if(gsim_fill_memview(0,"EC"))
	{
		g_free(x);
		return 1;
	}
	if(gsim_fill_memview(1,x))
	{
		g_free(x);
		return 1;
	}
	g_free(x);
	return 0;
}

gint cpo(void)
{
	gchar *x;
	x=get_address__();
	if(!x)
		return 1;
	if(gsim_fill_memview(0,"E4"))
	{
		g_free(x);
		return 1;
	}
	if(gsim_fill_memview(1,x))
	{
		g_free(x);
		return 1;
	}
	g_free(x);
	return 0;
}

gint cz(void)
{
	gchar *x;
	x=get_address__();
	if(!x)
		return 1;
	if(gsim_fill_memview(0,"CC"))
	{
		g_free(x);
		return 1;
	}
	if(gsim_fill_memview(1,x))
	{
		g_free(x);
		return 1;
	}
	g_free(x);
	return 0;
}

gint cnz (void)
{
	gchar *x;
	x=get_address__();
	if(!x)
		return 1;
	if(gsim_fill_memview(0,"C4"))
	{
		g_free(x);
		return 1;
	}
	if(gsim_fill_memview(1,x))
	{
		g_free(x);
		return 1;
	}
	g_free(x);
	return 0;
}

gint jmp (void)
{
	gchar *x;
	x=get_address__();
	if(!x)
		return 1;
	if(gsim_fill_memview(0,"C3"))
	{
		g_free(x);
		return 1;
	}
	if(gsim_fill_memview(1,x))
	{
		g_free(x);
		return 1;
	}
	g_free(x);
	return 0;
}

gint jc (void)
{
	gchar *x;
	x=get_address__();
	if(!x)
		return 1;
	if(gsim_fill_memview(0,"DA"))
	{
		g_free(x);
		return 1;
	}
	if(gsim_fill_memview(1,x))
	{
		g_free(x);
		return 1;
	}
	g_free(x);
	return 0;
}

gint jnc (void)
{
	gchar *x;
	x=get_address__();
	if(!x)
		return 1;
	if(gsim_fill_memview(0,"D2"))
	{
		g_free(x);
		return 1;
	}
	if(gsim_fill_memview(1,x))
	{
		g_free(x);
		return 1;
	}
	g_free(x);
	return 0;
}

gint jp (void)
{
	gchar *x;
	x=get_address__();
	if(!x)
		return 1;
	if(gsim_fill_memview(0,"F2"))
	{
		g_free(x);
		return 1;
	}
	if(gsim_fill_memview(1,x))
	{
		g_free(x);
		return 1;
	}
	g_free(x);
	return 0;
}

gint jm (void)
{
	gchar *x;
	x=get_address__();
	if(!x)
		return 1;
	if(gsim_fill_memview(0,"FA"))
	{
		g_free(x);
		return 1;
	}
	if(gsim_fill_memview(1,x))
	{
		g_free(x);
		return 1;
	}
	g_free(x);
	return 0;
}

gint jpe (void)
{
	gchar *x;
	x=get_address__();
	if(!x)
		return 1;
	if(gsim_fill_memview(0,"EA"))
	{
		g_free(x);
		return 1;
	}
	if(gsim_fill_memview(1,x))
	{
		g_free(x);
		return 1;
	}
	g_free(x);
	return 0;
}

gint jpo (void)
{
	gchar *x;
	x=get_address__();
	if(!x)
		return 1;
	if(gsim_fill_memview(0,"E2"))
	{
		g_free(x);
		return 1;
	}
	if(gsim_fill_memview(1,x))
	{
		g_free(x);
		return 1;
	}
	g_free(x);
	return 0;
}

gint jz (void)
{
	gchar *x;
	x=get_address__();
	if(!x)
		return 1;
	if(gsim_fill_memview(0,"CA"))
	{
		g_free(x);
		return 1;
	}
	if(gsim_fill_memview(1,x))
	{
		g_free(x);
		return 1;
	}
	g_free(x);
	return 0;
}

gint jnz (void)
{
	gchar *x;
	x=get_address__();
	if(!x)
		return 1;
	if(gsim_fill_memview(0,"C2"))
	{
		g_free(x);
		return 1;
	}
	if(gsim_fill_memview(1,x))
	{
		g_free(x);
		return 1;
	}
	g_free(x);
	return 0;
}

gint lda (void)
{
	if(gsim_fill_memview(0,"3A"))
		return 1;
	return gsim_fill_memview(1,op1);
}

gint lhld(void)
{
	if(gsim_fill_memview(0,"2A"))
		return 1;
	return gsim_fill_memview(1,op1);
}

gint shld(void)
{
	if(gsim_fill_memview(0,"22"))
		return 1;
	return gsim_fill_memview(1,op1);
}

gint sta (void)
{
	if(gsim_fill_memview(0,"32"))
		return 1;
	return gsim_fill_memview(1,op1);
}

gint ldax(void)
{
	if(g_ascii_strncasecmp(op1,"B",2)==0)
		return gsim_fill_memview(0,"0A");
	else
		return gsim_fill_memview(0,"1A");
}

gint lxi(void)
{
	gint i;
	for(i=0;i<4;i++)
		if(g_ascii_strncasecmp(op1,lxi_lookup[i].op1,2)==0)
			break;
	if(gsim_fill_memview(0,lxi_lookup[i].code))
		return 1;
	return gsim_fill_memview(1,op2);
}
		
gint mvi(void)
{
	gint i;
	for(i=0;i<8;i++)
		if(g_ascii_strncasecmp(op1,mvi_lookup[i].op1,2)==0)
			break;
	if(gsim_fill_memview(0,mvi_lookup[i].code))
		return 1;
	return gsim_fill_memview(0,op2);
}

gint stax(void)
{
	if(g_ascii_strncasecmp(op1,"B",2)==0)
		return gsim_fill_memview(0,"02");
	else
		return gsim_fill_memview(0,"12");
}

gint rst(void)
{
	gint i;
	i=atoi(op1);
	switch(i)
	{
		case 0 : return gsim_fill_memview(0,"C7");break;
			case 1 : return gsim_fill_memview(0,"CF");break;
				case 2 : return gsim_fill_memview(0,"D7");break;
					case 3 :return gsim_fill_memview(0,"DF");break;
						case 4 :return  gsim_fill_memview(0,"E7");break;
							case 5 :return gsim_fill_memview(0,"EF");break;
								case 6 : return gsim_fill_memview(0,"F7");break;
									case 7 : return gsim_fill_memview(0,"FF");break;
	}
	gsim_message(_("RST n : n must be less than 7"),GTK_MESSAGE_ERROR);
	return 1;
}
